﻿using System;

namespace Legalsoft.Truffer
{
    public class Vector<T> : System.IDisposable
    {
        /// <summary>
        /// size of array. upper index is nn-1
        /// </summary>
        private int nn { get; set; } = 0;
        private T[] v { get; set; } = null;

        public Vector()
        {
            this.nn = 0;
            this.v = null;
        }

        public Vector(int n)
        {
            this.nn = n;
            this.v = n > 0 ? new T[n] : null;
        }

        public Vector(int n, T a)
        {
            this.nn = n;
            this.v = n > 0 ? new T[n] : null;
            for (int i = 0; i < n; i++)
            {
                v[i] = a;
            }
        }

        public Vector( T[] a)
        {
            this.nn = a.Length;
            this.v = nn > 0 ? new T[nn] : null;
            for (int i = 0; i < nn; i++)
            {
                v[i] = a[i];
            }
        }
        
        public Vector(Vector<T> rhs)
        {
            this.nn = rhs.nn;
            this.v = nn > 0 ? new T[nn] : null;
            for (int i = 0; i < nn; i++)
            {
                v[i] = rhs[i];
            }
        }

        public T[] ToArray(int start = 0)
        {
            T[] r = new T[nn];
            for (int i = start; i < nn; i++)
            {
                r[i] = this[i];
            }
            return r;
        }

        public void FromArray(T[] r)
        {
            for (int i = 0; i < r.Length && i < v.Length; i++)
            {
                this[i] = r[i];
            }
        }

        public Vector<T> CopyFrom(Vector<T> rhs)
        {
            this.nn = rhs.nn;
            this.v = nn > 0 ? new T[nn] : null;
            for (int i = 0; i < nn; i++)
            {
                v[i] = rhs[i];
            }
            return this;
        }

        public T this[int i]
        {
            get
            {
#if _CHECKBOUNDS_
        if (i < 0 || i >= nn)
        {
            throw ("Vector subscript out of bounds");
        }
#endif
                return v[i];
            }
            set
            {
                v[i] = value;
            }
        }

        public int size()
        {
            return nn;
        }

        public void resize(int newn)
        {
            if (newn != nn)
            {
                nn = newn;
                v = nn > 0 ? new T[nn] : null;
            }
        }

        public void assign(int newn, T a)
        {
            if (newn != nn)
            {
                nn = newn;
                v = nn > 0 ? new T[nn] : null;
            }
            for (int i = 0; i < nn; i++)
            {
                v[i] = a;
            }
        }

        public void sort()
        {
            Array.Sort(v);
        }

        public T[] range(int start)
        {
            T[] r = new T[size() - start];
            for (int i = start; i < size(); i++)
            {
                r[i - start] = v[i];
            }
            return r;
        }

        public void Dispose()
        {
            if (v != null)
            {
                v = null;
            }
        }
    }
}

